/*
 *   Copyright 2021 zzh
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.aduib.boot.common.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Paths;
import java.util.Hashtable;

/**
 * @author ZZH
 * @version 1.0.0 条形码 二维码
 */
public class ZxingHelper {

  /**
   * 条形码编码
   *
   * @param contents
   * @param width
   * @param height
   * @param imgPath
   */
  public static void encode(String contents, int width, int height, String imgPath) {
    int codeWidth =
        3 + // start guard
            (7 * 6) + // left bars
            5 + // middle guard
            (7 * 6) + // right bars
            3; // end guard
    codeWidth = Math.max(codeWidth, width);
    try {
      BitMatrix bitMatrix =
          new MultiFormatWriter().encode(contents, BarcodeFormat.EAN_13, codeWidth, height, null);

      MatrixToImageWriter.writeToPath(bitMatrix, "png", Paths.get(imgPath));

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 条形码解码
   *
   * @param imgPath
   * @return String
   */
  public static String decode(String imgPath) {
    BufferedImage image = null;
    Result result = null;
    try {
      image = ImageIO.read(new File(imgPath));
      if (image == null) {
        throw new RuntimeException("the decode image may be not exit.");
      }
      LuminanceSource source = new BufferedImageLuminanceSource(image);
      BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

      result = new MultiFormatReader().decode(bitmap, null);
      return result.getText();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 二维码编码
   *
   * @param contents
   * @param width
   * @param height
   * @param imgPath
   */
  public static void encode2(String contents, int width, int height, String imgPath) {
    Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
    // 指定纠错等级
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
    // 指定编码格式
    hints.put(EncodeHintType.CHARACTER_SET, "GBK");
    try {
      BitMatrix bitMatrix =
          new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);

      MatrixToImageWriter.writeToPath(bitMatrix, "png", Paths.get(imgPath));

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 二维码解码
   *
   * @param imgPath
   * @return String
   */
  public static String decode2(String imgPath) {
    BufferedImage image = null;
    Result result = null;
    try {
      image = ImageIO.read(new File(imgPath));
      if (image == null) {
        throw new RuntimeException("the decode image may be not exit.");
      }
      LuminanceSource source = new BufferedImageLuminanceSource(image);
      BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

      Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
      hints.put(DecodeHintType.CHARACTER_SET, "GBK");

      result = new MultiFormatReader().decode(bitmap, hints);
      return result.getText();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}
